package com.dd.common.utils;

import com.dd.common.constans.TokenConstantKey;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class JwtUtil {
    private static final String SECRET_KEY = "secretKey"; // 用于签署JWT的密钥
    private static final long EXPIRATION_TIME = 60*60*60*24*30; // 令牌的过期时间（30天）
    private static final String TOKEN_PREFIX = "Bearer ";

    /**
     * 根据用户信息生成token
     * @param userID 用户名
     *
     * @return
     */

    public static String generateTokenByNmae(String userID,String username){
        HashMap<String, Object> map = new HashMap<>();
        map.put(TokenConstantKey.TOKEN_USER_ID_KEY,userID);

        map.put(TokenConstantKey.TOKEN_USER_NAME_KEY,username);
        return generateToken(map,"dd");
    }

    /**
     * 根据给定参数，生成JWT并加上TOKEN_PREFIX前缀
     *
     * @param claims    包含JWT所要负载的数据的键值对
     * @param subject   JWT的发行人
     * @return          加上前缀的JWT字符串
     */
    public static String generateToken(Map<String, Object> claims, String subject) {
        return TOKEN_PREFIX+ Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    /**
     * 获取JWT的Payload部分
     *
     * @param token     加上前缀的JWT字符串
     * @return          从JWT中解析出来的payload数据
     */
    public static <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }




    /**
     * 根据给定的token参数，从其中解析出JWT的所有Claims
     *
     * @param token     加上前缀的JWT字符串
     * @return          token中的所有键值对
     */
    public static Claims extractAllClaims(String token) {
        return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
    }

    /**
     * 判断距离令牌过期时间是否还有30秒
     *
     * @param token     加上前缀的JWT字符串
     * @return          如果令牌距离过期时间不足30秒，返回true
     */
    private static boolean isTokenCloseToExpiration(String token) {
        final Date expiration = extractClaim(token, Claims::getExpiration);
        final Date currentTime = new Date(System.currentTimeMillis());
        return expiration.before(new Date(currentTime.getTime() + 30000));
    }

    /**
     * 判断token是否过期
     *
     * @param token     加上前缀的JWT字符串
     * @return          如果token过期，返回true
     */
    public static boolean isTokenExpired(String token) {
        return extractClaim(token, Claims::getExpiration).before(new Date());
    }

    /**
     * 自动续签JWT
     *
     * @param token     加上前缀的JWT字符串
     * @return          新生成的JWT字符串
     */
    public static String refreshToken(String token) {
        final Claims claims = extractAllClaims(token);
        Map<String, Object> newClaims = new HashMap<>();
        newClaims.putAll(claims);
        if (isTokenCloseToExpiration(token)) {
            newClaims.put("additionalKey", "additionalValue");
            return generateToken(newClaims, claims.getSubject());
        } else {
            return token;
        }
    }


    public static String analysisToken(String token){
        Claims claims = JwtUtil.extractAllClaims(token);
        String userID=claims.get(TokenConstantKey.TOKEN_USER_ID_KEY,String.class);
        return  userID;
    }

    public static String analysisUserToken(String token){
        Claims claims = JwtUtil.extractAllClaims(token);
        String username=claims.get(TokenConstantKey.TOKEN_USER_NAME_KEY,String.class);
        return  username;
    }
}